const setup = require('./support/setup');
const base = setup.uri;
const isMSIE = !setup.NODE && /Trident\//.test(navigator.userAgent);

const assert = require('assert');
const request = require('../');

describe('request', function(){
  this.timeout(20000);
  describe('on redirect', () => {
    it('should retain header fields', done => {
      request
      .get(`${base}/header`)
      .set('X-Foo', 'bar')
      .end((err, res) => {
        try {
          assert(res.body);
          res.body.should.have.property('x-foo', 'bar');
          done();
        } catch(err) {
          done(err);
        }
      });
    })

    it('should preserve timeout across redirects', done => {
      request
      .get(`${base}/movies/random`)
      .timeout(250)
      .end((err, res) => {
        try {
          assert(err instanceof Error, 'expected an error');
          err.should.have.property('timeout', 250);
          done();
        } catch(err) {
          done(err);
        }
      });
    })

    it('should successfully redirect after retry on error', done => {
      const id = Math.random() * 1000000 * Date.now();
      request
      .get(`${base}/error/redirect/${id}`)
      .retry(2)
      .end((err, res) => {
        assert(res.ok, 'response should be ok');
        assert(res.text, 'first movie page');
        done();
      });
    });

    it('should preserve retries across redirects', done => {
      const id = Math.random() * 1000000 * Date.now();
      request
      .get(`${base}/error/redirect-error${id}`)
      .retry(2)
      .end((err, res) => {
        assert(err, 'expected an error');
        assert.equal(2, err.retries, 'expected an error with .retries');
        assert.equal(500, err.status, 'expected an error status of 500');
        done();
      });

    });
  });

  describe('on 303', () => {
    it('should redirect with same method', done => {
      request
      .put(`${base}/redirect-303`)
      .send({msg: "hello"})
      .redirects(1)
      .on('redirect', res => {
        res.headers.location.should.equal('/reply-method')
      })
      .end((err, res) => {
        if (err) {
          done(err);
          return;
        }
        res.text.should.equal('method=get');
        done();
      })
    })
  })

  describe('on 307', () => {
    it('should redirect with same method', done => {
      if (isMSIE) return done(); // IE9 broken

      request
      .put(`${base}/redirect-307`)
      .send({msg: "hello"})
      .redirects(1)
      .on('redirect', res => {
        res.headers.location.should.equal('/reply-method')
      })
      .end((err, res) => {
        if (err) {
          done(err);
          return;
        }
        res.text.should.equal('method=put');
        done();
      })
    })
  })

  describe('on 308', () => {
    it('should redirect with same method', done => {
      if (isMSIE) return done(); // IE9 broken

      request
      .put(`${base}/redirect-308`)
      .send({msg: "hello"})
      .redirects(1)
      .on('redirect', res => {
        res.headers.location.should.equal('/reply-method')
      })
      .end((err, res) => {
        if (err) {
          done(err);
          return;
        }
        res.text.should.equal('method=put');
        done();
      })
    })
  })
})
